package com.slb.slnwp.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @author wwq
 * @date: 2023-06-13 19:16:44
 * @desc: 通用方法类
 */
@Slf4j
public class Util {

    /**
     * 统计指定路径下的文件数量的工具方法。
     *
     * @param path 要统计文件数量的目录路径
     * @return 目录下的文件数量
     */
    public static int countFile(String path) {
        int count = 0;
        // 获取目录下的所有文件和子目录
        String[] folder = new File(path).list();
        // 判断目录是否存在
        if (null == folder || folder.length == 0) {
            // 如果目录不存在，记录日志并返回 0
            //log.info("文件夹: {} 不存在, 数据还未推送。", path);
            return count;
        }
        // 如果目录存在，获取文件数量
        count = folder.length;
        //log.info("{} 文件夹下的数据有：{}", path, count);
        return count;
    }

    /**
     * 统计指定目录下以指定前缀开头的文件数量的工具方法
     * @param directoryPath 目录路径
     * @param prefix 文件名前缀
     * @return
     */
    public static int countFilesWithPrefix(String directoryPath, String prefix) {
        // 根据目录路径创建 File 对象
        File directory = new File(directoryPath);
        // 获取目录下的所有文件
        File[] files = directory.listFiles();
        int count = 0;
        // 判断目录是否存在
        if (null == files || files.length == 0) {
            return count;
        }
        // 遍历目录下的所有文件
        for (File file : files) {
            // 判断文件名是否包含指定前缀
            if (file.getName().contains(prefix)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 计算当前数值预报时次
     * @param retrunFormat 返回类型  "1": 2023070212, "2": 20230702, "3": 12
     * @return
     */
    public static String getDateTimeToFamat(String retrunFormat) {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        String formattedDateTime = "";
        String formattedTime = "";
        String formattedDate = "";
        String result = "";
        if (now.getHour() >= 0 && now.getHour() < 12) {
            // 获取前一天的时间
            LocalDateTime previousDay = now.minus(1, ChronoUnit.DAYS);
            // 设置时间为前一天的12点
            LocalDateTime previousDayTwelve = previousDay.withHour(12).withMinute(0).withSecond(0);
            // 格式化输出
            DateTimeFormatter formatterDateTime = DateTimeFormatter.ofPattern("yyyyMMddHH");
            DateTimeFormatter formatterDate = DateTimeFormatter.ofPattern("yyyyMMdd");
            formattedDateTime = previousDayTwelve.format(formatterDateTime);
            formattedDate = previousDayTwelve.format(formatterDate);
            formattedTime = "12";
        } else {
            // 设置时间为当天的00点
            LocalDateTime currentDayMidnight = now.withHour(0).withMinute(0).withSecond(0);
            // 格式化输出
            DateTimeFormatter formatterDateTime = DateTimeFormatter.ofPattern("yyyyMMddHH");
            DateTimeFormatter formatterDate = DateTimeFormatter.ofPattern("yyyyMMdd");
            formattedDateTime = currentDayMidnight.format(formatterDateTime);
            formattedDate = currentDayMidnight.format(formatterDate);
            formattedTime = "00";
        }
        if ("1".equals(retrunFormat)) {
            result = formattedDateTime;
        } else if ("2".equals(retrunFormat)) {
            result = formattedDate;
        } else {
            result = formattedTime;
        }
        return result;
    }


    /**
     * 计算百分比(不足1%的按1%输出，超过100%的，按100%输出)
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param count    保留几位小数(0则不保留小数)
     * @return
     */
    public static String rateCount(int dividend, int divisor, int count) {
        String rate = "0";
        // 除数,被除数不能为0，否则返回0
        if (divisor != 0 && dividend != 0) {
            // 计算百分比
            double percentage = (double) dividend / divisor * 100;
            String format = "#";
            for (int i = 0; i < count; i++) {
                if (i == 0) {
                    format += ".";
                }
                format += "0";
            }
            DecimalFormat df = new DecimalFormat(format); // 设置保留小数的格式
            // 如果整除，则不保存小数，不足1%的按1%输出，超过100%的，按100%输出
            if (percentage < 1) {
                rate = "1%";
            } else if (percentage > 100) {
                rate = "100%";
            } else {
                rate = percentage == (int) percentage ? (int) percentage + "%" : df.format(percentage) + "%";
            }
        }
        return rate;
    }

    /**
     * 执行 Shell 命令的工具方法，并返回命令的输出结果
     * @param command 要执行的 Shell 命令
     * @return
     */
    public static String execShellCommand(String command) {
        // 用于存储命令执行的输出结果
        StringBuilder output = new StringBuilder();
        log.info("执行命令：{}", command);
        try {
            //String command = "ls /share/software/apps/SLNWP_USER/data/input/OBS/SA/20230702 | grep 'Z_RADR_I_Z9991_2023070200' | wc -l";
            // 创建 ProcessBuilder 对象，并设置命令
            ProcessBuilder processBuilder = new ProcessBuilder();
            processBuilder.command("bash", "-c", command);
            processBuilder.redirectErrorStream(true);

            // 启动进程执行命令
            Process process = processBuilder.start();
            // 读取命令输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;

            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
            // 等待命令执行完成
            process.waitFor();
            log.info("执行结果：{}", output);
        } catch (Exception e) {
            log.info("当前路径没有文件....{}", e);
            return "0";
        }
        // 判断输出结果中是否包含 "No such file or directory"，如果是，返回 "0"，否则返回输出结果
        if (output.toString().contains("No such file or directory")) {
            return "0";
        } else {
            return output.toString();
        }
    }

    /**
     * 在指定工作目录下执行 Shell 命令的工具方法，并返回命令的输出结果
     * @param workDir 工作目录路径
     * @param command 要执行的 Shell 命令
     * @return 命令执行的输出结果
     */
    public static String execShellCommand(String workDir, String command){
        StringBuilder output = new StringBuilder("");
        log.info("路径：{}, 执行的命令：{}", workDir, command);
        try {
            // 创建 ProcessBuilder 对象，并设置工作目录和命令
            ProcessBuilder pb = new ProcessBuilder();
            pb.directory(new File(workDir));
            pb.command("bash", "-c", "cd " + workDir + " && " + command);

            // 读取命令输出
            Process process = pb.start();
            // 读取命令输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;

            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
            // 等待命令执行完成
            int exitCode = process.waitFor();
            // 检查退出状态码
            if (exitCode == 0) {
                log.info("命令执行成功, {}", exitCode);
            } else {
                log.info("命令执行失败, {}", exitCode);
            }
        } catch (Exception e) {
            log.info("执行shell命令出错：{}", e);
        }
        log.info("执行结果：{}", output.toString());
        return output.toString();
    }

    /**
     * 获取用于预报的时间戳,判断当前时间所处的预报时次
     * 如果是0-12点，则设置时间为前一天的12时
     * 如果是12-24时，则设置时间为当天的00时
     * @return
     */
    public static String nwpForecastTime() {
        Date nowTime = new Date();
        // 当天日期
        String date = DateUtil.formatTime(nowTime, DateUtil.HH_DATA_FORMAT);
        // 当天日期（格式为小时数据）
        LocalDateTime now = LocalDateTime.now();
        String formattedDateTime = "";
        if (now.getHour() >= 0 && now.getHour() < 12) {
            // 获取前一天的时间
            LocalDateTime previousDay = now.minus(1, ChronoUnit.DAYS);
            // 设置时间为前一天的12点
            LocalDateTime previousDayTwelve = previousDay.withHour(12).withMinute(0).withSecond(0);
            // 格式化输出
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
            formattedDateTime = previousDayTwelve.format(formatter);
        } else {
            // 设置时间为当天的00点
            LocalDateTime currentDayMidnight = now.withHour(0).withMinute(0).withSecond(0);
            // 格式化输出
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHH");
            formattedDateTime = currentDayMidnight.format(formatter);
        }
        return formattedDateTime;
    }

    /**
     * 获取WRFOUT文件名字以及时间
     * @param wrfPath
     * @return
     */
    public static Map<String, String> getFilesName(String wrfPath) {
        Map<String, String> filesNameLst = new LinkedHashMap<>();
        // 指定目录路径
        //String directoryPath = "/share/software/apps/SLNWP_USER/data/output/MediumShortFCT/WRFOUT/2024022812/Short";
        // 创建File对象
        File directory = new File(wrfPath);
        // 检查目录是否存在
        if (!directory.exists()) {
            log.info("目录不存在！");
            return filesNameLst;
        }
        // 检查是否是一个目录
        if (!directory.isDirectory()) {
            log.info("指定路径不是一个目录！");
            return filesNameLst;
        }
        // 获取目录下的所有文件
        File[] files = directory.listFiles();
        // 遍历文件数组并打印文件名
        if (files != null) {
            for (File file : files) {
                if (file.isFile()) {
                    // 修改时间格式
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String lastModified = sdf.format(file.lastModified());
                    // 封装名字，时间
                    filesNameLst.put(file.getName(),lastModified);
                }
            }
        }
        return filesNameLst;
    }
}
